package com.wsc.indexer;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;

import static com.wsc.indexer.IndexerHTTPServer.indexer_2xx;
import static com.wsc.indexer.IndexerHTTPServer.indexer_3xx;
import static com.wsc.indexer.IndexerHTTPServer.indexer_4xx;
import static com.wsc.indexer.IndexerHTTPServer.indexer_Other;

import com.wsc.indexer.utils.HtmlData;
import com.wsc.indexer.utils.IndexerURLBean;

public class ServeClientRequest {
 private Logger log=Logger.getLogger(ServeClientRequest.class.getName());
 
 private IndexerConfig config = null;
 private String index_2xx_dir= null;
 private String index_3xx_dir= null;
 private String index_4xx_dir= null;
 
 private String index_other= null;
 
 private String WSDL_visited_index_dir = null;
 
 private String IndexDir = null;
 
 private HttpResponse response;
 
 private void initLocal(){
	 index_2xx_dir = config.getIndex_2xx_dir();
	 index_3xx_dir = config.getIndex_3xx_dir();
	 index_4xx_dir = config.getIndex_4xx_dir();
	 
	 index_other = config.getIndex_other_dir();
	 
	 IndexDir = config.getIndex_root_dir();
	 WSDL_visited_index_dir = config.getWSDL_visited_index_dir();
 }
 
 
	public void handleRequest(final HttpRequest request,
            final HttpResponse response,
            final HttpContext context,IndexerConfig config){

		// assgin IndexerConfig to Local Object.
		this.config=config ; 
		this.response = response;
		// Now Intialize all variables  in this class
		initLocal();
		
		int index = request.getRequestLine().getUri().indexOf('?');
		
		// Get the Query part of the requested path in HttpRequest.
		String querypart = request.getRequestLine().getUri()
				.substring(index + 1);

		// Construct a KEY-VALUE pair List from querypart string.
		// default delimator is &.

		List<NameValuePair> params = URLEncodedUtils.parse(querypart,
				Charset.defaultCharset());
 
		
		// check the list size.
		if (!params.isEmpty()) {

			// read key from NameValuePair object in List.
			String name = params.get(0).getName();

			// read value from NameValuePair object in List.
			String value = params.get(0).getValue();
			
		// Get second parameter from request
			
			
		log.debug("Got Request for "+name+":"+value);
		
			// If parameter is opearation

			if (IndexerOperations.OPERATION.equals(name)) {

				 
				
			//  The Request that Satisfy the following condition is:
			//   http://localhost:1234/index?operation=index&url=http://www.example.com/
				
				if (IndexerOperations.O_INDEX.equals(value)) {
					
					/*
					 * Get O_INDEX_NAME and navigate to that dir and get
					 * url to be index and index in navigated directory.
					 */

					log.debug("Request recieved for operation "+value);

					//Here The Complete request looks like:
					
					//  http://localhost:1234/index?operation=index&url=http://www.example.com/
					
					String value_key = params.get(1).getName();
					
					if(IndexerOperations.O_URL.equals(value_key)){
						
						log.info("Server Recieved a "+value_key+" Request...");
						
						// get second key from request.
						
						// get url, that to be indexed.
						
						String value_url = params.get(1).getValue();
						
						System.out.println("Got index request for url :"+value_url);
						
						String stauscode = params.get(2).getName() ;
					
						// Check the status code param is in request or not
						
						if(IndexerOperations.O_STATUS_CODE.equals(stauscode)){
						
							int status_code_of_url = Integer.parseInt(params.get(2).getValue());
							
							// this Obejct Used later 
							String Index_Dir = null;
							
							switch(status_code_of_url){
							// If status code is 2xx means that the crawlig of this URL is successfull.
							case 200 :
							case 201 :
							case 202 :
							case 203 :
							case 204 :
							case 205 :
							case 206 :
								// Set the visited url index to index_2xx_dir 
								Index_Dir = index_2xx_dir ;
								// Index url in 2xx index
								index_2xx(value_url);
								break;
								
							// If status code is 3xx means that the crawlig of this URL is Unsuccessfull.
								
							case 300:
							case 301:
							case 302:
							case 303:
							case 304:
							case 305:
							case 306:
								// Set the visited url index to index_3xx_dir
								Index_Dir = index_3xx_dir;
								
								// Index the url in index3xx dir
								
								index_3xx(value_url);
								break;
							// If status code is 3xx means that the crawlig of this URL is Unsuccessfull.	
							case 400:	
							case 401:
							case 402:
							case 403:
							case 404:
							case 405:
							case 406:
							case 407:
								// Set the visited url index to index_4xx_dir
								Index_Dir = index_4xx_dir ;
								// Index the url in index3xx dir
								
								index_4xx(value_url);
								
								break;
							default :
								Index_Dir = IndexDir+"/other";
								
								// If status code is none of the above cases
								// the index it in other separate index.
								
								index_Other(value_url);
							}
						
						
						
							
						}else{
							log.debug("Url ("+value_url+") is already visited.");
							
							response.setStatusCode(HttpStatus.SC_OK);
							
							// Construct a String Entity, with proper message.
							
							NStringEntity entity = null;
							try {
								entity = new NStringEntity("("+value_url+") is already visited.");
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
							}
						
							// And set it in Response.
							
							response.setEntity(entity);
							log.debug("Request Served Successfully");
						}
							
						
					}
					
				} else if(IndexerOperations.O_VSTATUS.equals(value)){

					// If request is for vstatus
					
					// then read second keyvalue pair, i.e (url = url to be checked)
					String key_url = params.get(1).getName();
					
					if(IndexerOperations.O_URL.equals(key_url)){
						
						log.info("Server Recieved a "+IndexerOperations.O_VSTATUS+" Request...");
						
						// get url, that to be indexed.
						
						String value_url = params.get(1).getValue();
						
						System.out.println("Got Visited request for url :"+value_url);
					
						// checking whether the requested url is visited or not.
						
						Boolean status=VisitedUrls.isVisited(value_url, config);
						
						NStringEntity entity = null;
						try {
							entity = new NStringEntity("Is Visited: "+status);
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						}
						
						response.setEntity(entity); // edit : Importent
						
					}
					
				}else if(IndexerOperations.STOP_INDEXER.equals(value)){
					
					// Clean the resources hold by this class,
					// and close all indexers cleanly
					log.debug("Got request to stop Indexer Server.");
					log.debug("Flushing out all indexer descriptors");
					
					this.flush();
					
				} else if(IndexerOperations.START_INDEXER.equals(value)){
					
					log.debug("Got request to start Indexer Server.");
					// Start Indexer again
					this.startIndexer();
					
				}else{
					
					// IMPLEMENT OTHER OPERATION  REQUESTS VALUES HERE.
					
					
					log.debug("Opeartion value (" + value
							+ ") not yet Implemented");
					response.setStatusCode(HttpStatus.SC_NOT_FOUND);

					// Set Entity message notfound in HTML.
					
					NStringEntity entity = new NStringEntity(
							HtmlData.getOperationValueNotSupported(value),
							ContentType.create("text/html", "UTF-8"));

					// Set the Entity in Response meassage.
					response.setEntity(entity); // edit : not mandatory.
					
				}

			} else {

				log.warn("Unsupported operation (" + name
						+ ") found in request.");

				// If operation parameter is not equals to
				// CrawlerOperations.OPERATION then send 404 notfound
				// message.
		       
				response.setStatusCode(HttpStatus.SC_NOT_FOUND);

				// Set Entity message notfound in HTML.
				NStringEntity entity = new NStringEntity(
						HtmlData.getOperationNotSupported(name),
						ContentType.create("text/html", "UTF-8"));

				// Set the Entity in Response meassage.
				response.setEntity(entity); // edit : not mandatory.

			}

		}

	}

	
	
// Create new Instances of all indexers
	
	private void startIndexer() {
		// Instantiate the indexers
		
		log.debug("Starting all indexers...");
		
		if(indexer_2xx == null)
			indexer_2xx = new LuceneIndexer(config.getIndex_2xx_dir());
		
		if(indexer_3xx == null)
			indexer_3xx = new LuceneIndexer(config.getIndex_3xx_dir());
		
		if(indexer_4xx == null)
			indexer_4xx = new LuceneIndexer(config.getIndex_4xx_dir());
		
		if(indexer_Other == null)
			indexer_Other = new LuceneIndexer(config.getIndex_other_dir());
		

		// now check all indexers, whether they are properly instantiated or not.
		
		if(indexer_2xx != null && indexer_3xx != null && indexer_4xx != null && indexer_Other != null)
		{
			NStringEntity entity = null;
			try {
				entity = new NStringEntity("all indexers are SuccessFully started .");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
						response.setEntity(entity);
						log.debug("Request Served Successfully");
						 	
						response.setEntity(entity);
			}
	}
	
	// close all indexes opened in IndexerHTTPServer class.

	private void flush() {
	
		NStringEntity entity = null;
		
		if(indexer_2xx != null && indexer_3xx != null && indexer_4xx != null && indexer_Other != null)
		{
		indexer_2xx.closeIndex(); indexer_2xx =null;
		indexer_3xx.closeIndex(); indexer_3xx = null;
		indexer_4xx.closeIndex(); indexer_4xx = null;
		indexer_Other.closeIndex(); indexer_Other = null;
		
		try {
			entity = new NStringEntity("Flushing all indexers Is SuccessFull");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		}else {
			try {
				entity = new NStringEntity("It's seems to be all indexers are already flushed out.");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}		
		// Construct a String Entity, with proper message.
	
					
					// And set it in Response.
					
					response.setEntity(entity);
					log.debug("Request Served Successfully");
					 	
					response.setEntity(entity);
		}


	private void index_Other(String value_url) {
		 
		NStringEntity entity = null;
		// checking whether the requested url is visited or not.
		
		Boolean status=VisitedUrls.isVisited(value_url,config);
		
		// If and only of the url is not indexed then only index the url.
		
		if(!status){
			
			log.debug("Indexing URL :"+value_url);
			
			response.setStatusCode(HttpStatus.SC_OK);
			
				// Index URL
				IndexerURLBean bean = new IndexerURLBean();
				
				log.debug("Setting values to bean :"+value_url);
				
				bean.setUrl(value_url);
				
				bean.setCrawledBy("");
				
				// Get the current timestamp
				
				bean.setTime(new Timestamp((new Date()).getTime()));
				
				//	Index the bean
				if(indexer_Other !=null ){
				indexer_Other.index(bean);
				log.debug("Indexing URL :"+value_url+" Successfull.");
			 

			// Construct a String Entity, with proper message.
			
			try {
				entity = new NStringEntity("Indexing URL :"+value_url+" Is SuccessFull");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			// And set it in Response.
			
			response.setEntity(entity);
			log.debug("Request Served Successfully");
				}
				else{
					try {
						entity = new NStringEntity("Indexer is shutdown now. \n Indexer is shutdown unable to index url:"+value_url);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
			// And set it in Response.
			
					response.setEntity(entity);
					log.debug("Indexer is shutdown unable to index url:"+value_url);
				}
			
			}else{
				
				try {
					log.debug("URL "+value_url+" already visited..");
					entity = new NStringEntity("URL :"+value_url+" Is already Indexed");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				// And set it in Response.
				
				response.setEntity(entity);
			}
				
		
	}


	
	private void index_2xx(String value_url) {
		NStringEntity entity = null;
		// checking whether the requested url is visited or not.
		
		Boolean status=VisitedUrls.isVisited(value_url, config);
		
		// If and only of the url is not indexed then only index the url.
		
		if(!status){
			
			log.debug("Indexing URL :"+value_url);
			
			response.setStatusCode(HttpStatus.SC_OK);
			
				// Index URL
				IndexerURLBean bean = new IndexerURLBean();
				
				bean.setUrl(value_url);
				
				bean.setCrawledBy("");
				
				// Get the current timestamp
				
				bean.setTime(new Timestamp((new Date()).getTime()));
				
				//	Index the bean
				if(indexer_2xx !=  null)
				{
					indexer_2xx.index(bean);
				 
					// Construct a String Entity, with proper message.
			
					try {
						entity = new NStringEntity("Indexing URL :"+value_url+" Is SuccessFull");
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
			// And set it in Response.
			
					response.setEntity(entity);
					log.debug("Request Served Successfully");
				}else {
					try {
						entity = new NStringEntity("Indexer is shutdown now. \n unable to index url:"+value_url);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
			// And set it in Response.
			
					response.setEntity(entity);
					log.debug("Indexer is shutdown unable to index url:"+value_url);
				}
				
			}else{
				
				try {
					log.debug("URL "+value_url+" already visited..");
					entity = new NStringEntity("URL :"+value_url+" Is already Indexed");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				// And set it in Response.
				
				response.setEntity(entity);
			}
				
	}
	
	
	private void index_3xx(String value_url) {
		NStringEntity entity = null;
		// checking whether the requested url is visited or not.
		
		Boolean status=VisitedUrls.isVisited(value_url, config);
		
		// If and only of the url is not indexed then only index the url.
		
		if(!status){
			
			log.debug("Indexing URL in  3xx_index:"+value_url);
			
			response.setStatusCode(HttpStatus.SC_OK);
			
				// Index URL
				IndexerURLBean bean = new IndexerURLBean();
				
				bean.setUrl(value_url);
				
				bean.setCrawledBy("");
				
				// Get the current timestamp
				
				bean.setTime(new Timestamp((new Date()).getTime()));
				
				//	Index the bean in 3xx_index
				if(indexer_3xx !=  null){
					
				
				indexer_3xx.index(bean);
				 
			 

			// Construct a String Entity, with proper message.
			
			try {
				entity = new NStringEntity("Indexing URL :"+value_url+" Is SuccessFull");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			// And set it in Response.
			
			response.setEntity(entity);
			log.debug("Request Served Successfully");
			}else{
				try {
					entity = new NStringEntity("Indexer is shutdown now. \n Indexer is shutdown unable to index url:"+value_url);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
		// And set it in Response.
		
				response.setEntity(entity);
				log.debug("Indexer is shutdown unable to index url:"+value_url);
			}
			
			}else{
				
				try {
					log.debug("URL "+value_url+" already visited..");
					entity = new NStringEntity("URL :"+value_url+" Is already Indexed");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				// And set it in Response.
				
				response.setEntity(entity);
			}
				
	}


	
	private void index_4xx(String value_url) {
		NStringEntity entity = null;
		// checking whether the requested url is visited or not.
		
		Boolean status=VisitedUrls.isVisited(value_url, config);
		
		// If and only of the url is not indexed then only index the url.
		
		if(!status){
			
			log.debug("Indexing URL in  4xx_index:"+value_url);
			
			response.setStatusCode(HttpStatus.SC_OK);
			
				// Index URL
				IndexerURLBean bean = new IndexerURLBean();
				
				bean.setUrl(value_url);
				
				bean.setCrawledBy("");
				
				// Get the current timestamp
				
				bean.setTime(new Timestamp((new Date()).getTime()));
				
				//	Index the bean in 4xx_index
				if(indexer_4xx != null){
				indexer_4xx.index(bean);
				 
			 

			// Construct a String Entity, with proper message.
			
			try {
				entity = new NStringEntity("Indexing URL :"+value_url+" Is SuccessFull");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			// And set it in Response.
			
			response.setEntity(entity);
			log.debug("Request Served Successfully");
				}else{
					try {
						entity = new NStringEntity("Indexer is shutdown now. \n Indexer is shutdown unable to index url:"+value_url);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
			// And set it in Response.
			
					response.setEntity(entity);
					log.debug("Indexer is shutdown unable to index url:"+value_url);
				}
			}else{
				
				try {
					log.debug("URL "+value_url+" already visited..");
					entity = new NStringEntity("URL :"+value_url+" Is already Indexed");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				// And set it in Response.
				
				response.setEntity(entity);
			}
				
	}

	
	
}
